package com.cgah

/*
Done - B-1: Bids have the following required fields: amount and date/time of bid (integration test)
Done - B-2: Bids are required to be for a Listing (integration test)
Done - B-3: Bids are required to have a bidder (Customer) (integration test)

really this is a bid requirement?
Done - B-4: @see Listing.groovy - A Listing has a list of Bids for that Listing (integration test) ?
Done - B-5: The Bid amount must be at least .50 higher than the previous Bid for the same item (integration test)

TODO - The Bid amount must be at least .50 higher than the previous Bid for the same item (integration test)
B-6: When a Listing is saved, any new Bids added for the listing must be saved (integration test)
-- listing save better just cascade for one to many, else grails is bunk! wtf, why test basic grails functionality?
 */

class Bid implements Comparable {
    private static final float BID_INC = 0.5f;
    // users should never gets to set the date and time on creation
    // but we cannot prevent that so the controller will have to!
	Date dateTime = new Date();
	Float amount;
    Float nextMinBid;


	static belongsTo = [customer:Customer];
//    static fetchMode = [customer:"eager"];

    static hasOne = [listing:Listing];
//  this shit don't work in named queries
//    static fetchMode = [customer:"eager"];

     static transients = ['dateTimeString'];

    static constraints = {
	    dateTime(nullable: false);
        amount(nullable: false);
        listing(nullable: false,
                validator: {theListing,  thisObject ->
                    float currMaxPrice = (theListing.bids == null || theListing.bids.isEmpty()) ? theListing.startingBidPrice : theListing.bids.max().amount ;
                    currMaxPrice = currMaxPrice.longValue() + Bid.BID_INC;
                    if (! (currMaxPrice <= thisObject.amount)) {
                        println "failed"
                        return "New Bid must be \$0.50 more than the max bid"
                    }
                    thisObject.nextMinBid = thisObject.amount + Bid.BID_INC;
                    return true
                }
        );
	    customer(nullable: false);
    }

    // we need the customer info


    // this is SOOOOOOOOOOOOOOOOOOOOOOOOOOOO unnecessary and inefficient
    // it's shit like this that makes a good framework junk, because stupid people fail to learn
    // DB concepts and work with SQL, everyone tries to create some more stupid shit and do it with some
    // even more stupid syntax that they think totally makes all the perfect sense, SQL is not perfect
    // but at least it makes sense and it's fuking standard mofos!  get your shit standardized and we might use it
    static namedQueries = {
        lastTen { listing ->
            //  this shit doesn't work either
            //fetchMode('customer', org.hibernate.FetchMode.JOIN)
            join 'customer'
            eq('listing', listing)
            order('id', 'desc')
        }
    }


    public int compareTo(other) {
         return (this.amount - other.amount) > 0 ? 1 : ( (this.amount - other.amount) == 0 ? 0 : -1);
     }

    // omg for the sake of readability!
    // yeah this should be locale specific, but fthat
    public String toString () {
        return ("" +  DateNumberFormatter.formatDate(dateTime) + " \$" + DateNumberFormatter.formatNumber(amount))
    }

//    String getDateTimeString() {
//        return DateNumberFormatter.formatDate(dateTime)
//    }
}
